#ifndef MODBUS_UART_H
#define MODBUS_UART_H

#include "dialog.h"
#include "dialogd.h"

#include <QMainWindow>
#include <QSerialPort>//串口类
#include <QDebug>//调试输出类
#include <QSerialPortInfo>//串口信息类
#include <QMessageBox>//提示框类
#include <QTimer>//定时器类
#include <QThread>//多线程
#include <QSettings>
#include <QTableWidget>


#define ADDRESS_MAX 65535
#define CRC_FLAG 0


QT_BEGIN_NAMESPACE
namespace Ui { class modbus_uart; }
QT_END_NAMESPACE

class modbus_uart : public QMainWindow
{
    Q_OBJECT

public:
    modbus_uart(QWidget *parent = nullptr);
    ~modbus_uart();

    //串口对象
    QSerialPort Uart_Objects;//串口对象
    QSerialPort* m_serialport;
    QSerialPortInfo   Uart_Objects_info;//串口信息
    QList<QSerialPortInfo>  uart_info;//串口信息链表
    QTimer uart_time;//定时器类 用于自动发送数据
    QTimer uart_Receive_time;//定时器类 用于自动发送数据
    QTabWidget *tabWidget;
    QWidget *tab;
    QTableWidget *table_coil;
    QWidget *tab_2;
    QTableWidget *tableregs;
    QString msg;

    Dialog *dialog=nullptr;//0f功能码
    DialogD *dialogd=nullptr;//10功能码

    int receive_value=0;
    int send_value=0;

 signals:


private slots:

        void UART_OPEN_SLOTS(bool );//串口打开事件
        void UART_CLOSE_SLOTS(bool );//串口关闭事件
        void UART_send_SLOTS( );//串口发送事件
        void UART_Flush_SLOTS( );//刷新可用串口
        void UART_receive_SLOTS();//串口接收事件
        void UART_eerom_SLOTS(int y);//串口发生错误 槽函数
        void UART_time_SLOTS();//定时器时间到达槽函数
        void UART_time_run_SLOTS(bool );//定时器时间到达槽函数
        void on_receive_pushButton_clicked();//接收字节清零
        void on_send_pushButton_clicked();//发送字节清零
        void readMyComA(QByteArray temp);//读取串口数据帧并处理
        void hide_SLOTS();//隐藏控件槽函数
        void UART_setup_SLOTS();//设置参数
        void str_add_CRC(QString str);
        void table_dataInit();//表格初始化
        void ReadOutIniData(void);
        void init();//初始化
        void Updateregister(quint16 num, quint16 satrtaddr,QVector<quint16> bar);//更新寄存器表
        void Updatecoil(quint16 num, quint16 satrtaddr,QString bac);//更新线圈表
        void timerShow();//控件显示时间
        void showmsg(QString msg);
        void on_send_msg_clicked();     //发送槽函数
        void on_coilsetepbtn_clicked(); //设置0F功能码参数
        void on_regsetupbtn_clicked(); //设置10功能码参数
       void  wirtTablec(quint16 num, quint16 satrtaddr,QString bac);
       void  wirtTabler(quint16 num, quint16 satrtaddr,QVector<quint16> bar);
       //超时重发
       //void senddatetwice(QByteArray);
       //历史数据保存
       void on_historyBtn_clicked();
       void resendShow();

private:
    Ui::modbus_uart *ui;   
    modbus_uart * mb_msg;
    QSettings* readsetings=nullptr;
    //计数位
    int timeout = 0;
    //串口开闭标志
    bool uartIsOpen=false;
    //串口数据缓冲
    QByteArray uartSrcData;
    //当前时间定时器对象
    QTimer * m_timer;
    QTimer * m_resendtimer;
    QTimer *rcvDataTimer;
    QByteArray sendArray;
    //缓存数组
    QVector<quint16> bar;
    bool sendflag = false;
    quint8 msgbuf[256];
    bool UART_RUN = false;//软件串口是否打开标志位
    //初始化请求报文数组
    QByteArray requestMessage;
    QSettings* readseting=nullptr;
    QLabel *date;
    //地址起始地址即数量信息
     QVector<quint16> inf;
     QByteArray coildata;
     QByteArray resenddata;
     QVector<quint16> regdata;
     int resendNumber=0;
    quint8 m_code=0xff;


    void System_uart_init();//串口初始化函数

    //0f功能码封装
    void funCode0f(quint8 addr,quint16 startaddr,quint16 num,QByteArray bas);
    //10功能码封装
    void funCode10(quint8 addr,quint16 startaddr,QVector<quint16> addrvalue);
    //封装函数
    void packageSartc(quint8 addr,quint8 funcode,quint16 startaddr,quint16 num,QByteArray ba,QVector<quint16>regs);
    //CRC校验
    quint16 crc16ForModbus(const QByteArray &data,int flag);
    uint  CRC16_Calc(uchar *pBuf, uint uLen);
    //将读取的寄存器数据写入ini文件
    void WirteRegsDataToIni(quint16 startaddr, quint16 num,QVector<quint16> ba);
    //将读取的线圈数据写入ini文件
    void WirteCoilDataToIni(quint16 satrt, QString CoilData);
    void ParseResponseMessage(QByteArray responseMessage);
    //01 03功能码解析
    void analysis010(QByteArray responseMessage);
    //10 0F功能码解析
    void analysis10F(QByteArray responseMessage);
    //异常码解析
    void RTUExceptionCodeJudge(QByteArray responseMessage);
    //超时处理
    void timeout_handler();
    //读出寄存器并提示
    void ReadRegsPackMsgToShow(quint16 startaddr, quint16 num, QByteArray msg);
     //读出线圈值并提示
    void ReadCoilPackMsgToShow(quint16 startaddr, quint16 num, QByteArray msg);
    //写入线圈提示
    void WirteCoilPackMsgToShow(quint16 startaddr, quint16 num, QByteArray msg);
    //写入寄存器提示
    void WirteRegsPackMsgToShow(quint16 startaddr, quint16 num, QByteArray msg);


protected:
    // void timerEvent(QTimerEvent * event);


};
#endif// UART_H
